﻿/*! @file extdevice.cpp
 * @brief implements the ExtDevice Class
 *
 * TODO: Android v1.5 processing (contacts2.db ...)
 */

#include "extdevice.h"
#include "extdevicedlg.h"
#include "providerdlg.h"

#include <QDateTime>
#include <QDebug>
#include <QDir>
#include <QMessageBox>
#include <QObject>
#include <QProcess>
#include <QSettings>

/*! @brief Konstruktor
 * @callgraph
 * @callergraph
 */
ExtDevice::ExtDevice(QObject* parent)
    :QObject(parent)
{
    counter = 0;    // for on_reloadDevices
    deviceLst = getDevices();

    if(deviceLst.size() == 0) {
        deviceLst << tr("Kein Device gefunden.");
        qDebug() << "ExtDevice\t|No devices attached";
        return;
    }
    else {
        qDebug() << "ExtDevice\t|Found devices:";
        for(int i = 0; i<deviceLst.size(); ++i)
            qDebug() << QString("%1: %2").arg(i).arg(deviceLst.at(i));
    }

    extDevDlg = new ExtDeviceDlg(deviceLst);

    connect(extDevDlg, SIGNAL(deviceChanged(QString)),
            this, SLOT(getProperties(QString)));
    connect(extDevDlg, SIGNAL(directoryChanged(QString)),
            this, SLOT(expoDirChanged(QString)));
    connect(extDevDlg, SIGNAL(gotDevice(QString)),
            this, SLOT(sendDeviceToMainWindow(QString)));
    connect(extDevDlg, SIGNAL(doExport(QString, QString)),
            this, SLOT(getFiles(QString, QString)));
    connect(extDevDlg, SIGNAL(expoDone()),
            this, SLOT(on_done()));
    connect(extDevDlg, SIGNAL(logRequest(QString)),
            this, SLOT(on_logRequest(QString)));
    connect(extDevDlg, SIGNAL(propertiesRequest(QString)),
            this, SLOT(on_propertiesRequest(QString)));
    connect(extDevDlg, SIGNAL(providerRequest(QString)),
            this, SLOT(on_providerRequest(QString)));
    connect(extDevDlg, SIGNAL(reloadDevices(QString)),
            this, SLOT(on_reloadDevices(QString)));

    extDevDlg->show();
}

/** @brief ExtDevice Destructor
 * @callgraph
 * @callergraph
 */
ExtDevice::~ExtDevice()
{
    // TODO: close me proper
    adbProcess->close();
    qDebug() << "ExtDevice\t|extDevice deleted!";
}

/**
 * @brief sets selectedDir
 *
 * @fn ExtDevice::expoDirChanged
 * @param dir
 * @return QString
 */
QString ExtDevice::expoDirChanged(QString dir)
{
    qDebug() << "ExtDevice\t|recieved expoDirChanged:" << dir;
    selectedDir = dir;

    return selectedDir;
}

/**
 * @brief recursiv calling adb cmd again, selects expo dirs
 *
 * @fn ExtDevice::finishedProcess
 * @param exitCode
 * @param exitStatus
 */
void ExtDevice::finishedProcess(int exitCode, QProcess::ExitStatus exitStatus)
{
    Q_UNUSED(exitStatus);
    QString tmpDir;

    extDevDlg->setLogTextViewText(tr("fertig! exitCode: %1").arg(exitCode), Qt::black);
    if(idxProcess < sqliteFiles.size() - 1) {
        idxProcess++;

        // create and set expo dir per file
        if(!QDir(QDir::toNativeSeparators(selectedDir + "/" + sqliteFiles.at(idxProcess))).exists())
            if(!QDir(selectedDir).mkdir(QDir::toNativeSeparators(sqliteFiles.at(idxProcess))))
                qDebug() << "ExtDevice\t|cannot create Folder:" << selectedDir + "/" + sqliteFiles.at(idxProcess);
        tmpDir = selectedDir + "/" + sqliteFiles.at(idxProcess);

        // next line: arguments to export files
        QString expoFile = "/data/data/"
                + sqliteFiles.at(idxProcess)
                + "/databases/";

        arguments.clear();
        arguments << "-s" << selectedDevice << "pull"
                  << expoFile
                  << QDir::toNativeSeparators(tmpDir);

        // just debug block
        QString cmd4log = command;
        for(int j=0; j<arguments.size(); ++j) {
            cmd4log += ' ';
            cmd4log += arguments.at(j);
        }
        qDebug() << "ExtDevice\t|running:" << cmd4log;
        // ---

        extDevDlg->setLogTextViewText(cmd4log, Qt::blue);

        adbProcess = new QProcess();
        adbProcess->start("adb", arguments);

        // display Output
        connect(adbProcess, SIGNAL(readyReadStandardOutput()),
                this, SLOT(stdoutMsg()));
        connect(adbProcess, SIGNAL(readyReadStandardError()),
                this, SLOT(stderrMsg()));
        connect(adbProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
                this, SLOT(finishedProcess(int,QProcess::ExitStatus)));
    }
    else
        // no other process started
        extDevDlg->enableCloseButton();
}

/**
 * @brief gets connected devices/emulators
 *
 * @fn ExtDevice::getDevices
 * @return QList<QString>
 */
QList<QString> ExtDevice::getDevices()
{
    QList<QString> tmpdev;
    QString tmpbuf;

    arguments.clear();
    arguments << "devices";

    adbProcess = new QProcess;

    adbProcess->start("adb", arguments);

    if(!adbProcess->waitForStarted()) {
        qDebug() << "ExtDevice\t|error exec adb command:" << command << arguments.at(0);
        tmpdev << "Error";
        QMessageBox msg(QMessageBox::Warning,
                             tr("Fehler"),
                             tr("adb Befehl konnte nicht ausgeführt werden.\n"
                                "Ist die Android Debug Bridge installiert\n"
                                "und im Systempfad eingetragen?"),
                             QMessageBox::Cancel);
        msg.exec();

        return tmpdev;
    }
    while(adbProcess->waitForReadyRead()) {
        tmpbuf.append(adbProcess->readAll());
        tmpdev << parseDevicesResult(tmpbuf);
    }

    if(tmpdev.size() == 0) {
        tmpdev << tr("Keine Devices gefunden");
        return tmpdev;
    }

    getProperties(tmpdev.at(0));
    Q_EMIT deviceListReady(tmpdev);
    return tmpdev;
}

/**
 * @brief get files from device, on finish call for next file
 *
 * @fn ExtDevice::getFiles
 * @param dev
 * @param dir
 */
void ExtDevice::getFiles(QString dev, QString dir)
{
    QDateTime timestamp = QDateTime::currentDateTime();

    // get properties to write to file
    qDebug() << "ExtDevice\t|get properties";
    extDevDlg->setLogTextViewText("getting properties ...", Qt::gray);
    QString tmpbuf;
    arguments.clear();
    arguments << "-s" << dev << "shell" << "getprop";

    adbProcess = new QProcess;
    adbProcess->start("adb", arguments);

    if(!adbProcess->waitForStarted()) {
        qDebug() << "ExtDevice\t|error exec adb command:" << command << arguments.at(0);
        QMessageBox msg(QMessageBox::Warning,
                             tr("Fehler"),
                             tr("adb Befehl konnte nicht ausgeführt werden.\n"
                                "Ist die Android Debug Bridge installiert\n"
                                "und im Systempfad eingetragen?"),
                             QMessageBox::Cancel);
        msg.exec();
        return;
    }
    tmpbuf.append("Export von: " + dev + " am: "
                  + QDateTime::currentDateTime().toString(Qt::ISODate) + '\n');
    while(adbProcess->waitForReadyRead()) {
        tmpbuf.append(adbProcess->readAll());
    }

    // get logs from device to write to file
    qDebug() << "ExtDevice\t|get logs";
    extDevDlg->setLogTextViewText("getting logs ...", Qt::gray);
    QString logbuf;
    arguments.clear();
    arguments << "-s" << dev << "shell" << "dmesg";

    adbProcess = new QProcess;
    adbProcess->start("adb", arguments);

    if(!adbProcess->waitForStarted()) {
        qDebug() << "ExtDevice\t|error exec adb command:" << command << arguments.at(0);
        QMessageBox msg(QMessageBox::Warning,
                             tr("Fehler"),
                             tr("adb Befehl konnte nicht ausgeführt werden.\n"
                                "Ist die Android Debug Bridge installiert\n"
                                "und im Systempfad eingetragen?"),
                             QMessageBox::Cancel);
        msg.exec();
        return;
    }
    logbuf.append(tr("dmesg von: ") + dev + " am: "
                  + QDateTime::currentDateTime().toString(Qt::ISODate) + '\n');
    while(adbProcess->waitForReadyRead()) {
        logbuf.append(adbProcess->readAll());
    }

    // pull files from device
    command = "adb";
    selectedDevice = dev;
    baseDir = dir;
    QString subDir = dev + '_' + timestamp.toString("yyyyMMddhhmmss");

    if(!QDir(QDir::toNativeSeparators(baseDir + '/' + subDir)).exists())
        QDir(baseDir).mkdir(subDir);

    selectedDir = QDir::toNativeSeparators(baseDir + "/" + subDir);

    // write properties file
    qDebug() << "ExtDevice\t|write properties";
    QFile propertiesFile(QDir::toNativeSeparators(selectedDir + "/" + dev + "_getprop.txt"));
    if(!propertiesFile.open(QIODevice::WriteOnly | QIODevice::Text))
        qDebug() << "ExtDevice\t|Error opening properties file";
    QTextStream out(&propertiesFile);
    out << tmpbuf.trimmed();
    propertiesFile.close();

    // write log file
    qDebug() << "ExtDevice\t|write logs:" << arguments;
    QFile logsFile(QDir::toNativeSeparators(selectedDir + "/" + dev + "_dmesg.txt"));
    if(!logsFile.open(QIODevice::WriteOnly | QIODevice::Text))
        qDebug() << "ExtDevice\t|Error opening log file";
    QTextStream log(&logsFile);
    log << logbuf.trimmed();
    logsFile.close();

    if(sqliteFiles.isEmpty()) {
        // List of files to export
        sqliteFiles.append("com.android.providers.telephony");
        sqliteFiles.append("com.android.providers.contacts");
        sqliteFiles.append("com.dropbox.android");
        sqliteFiles.append("com.android.browser");
        sqliteFiles.append("com.android.browser");
        sqliteFiles.append("com.google.android.gm");
        sqliteFiles.append("com.android.email");
        sqliteFiles.append("com.android.providers.settings");
    }

    if(sqliteFiles.size() > 0) {
        QString tmpDir;
        idxProcess = 0;

        // create and set expo dir per file
        if(!QDir(QDir::toNativeSeparators(selectedDir + "/" + sqliteFiles.at(idxProcess))).exists())
            if(!QDir(selectedDir).mkdir(QDir::toNativeSeparators(sqliteFiles.at(idxProcess))))
                qDebug() << "ExtDevice\t|cannot create Folder:" << selectedDir + "/" + sqliteFiles.at(idxProcess);
        tmpDir = selectedDir + "/" + sqliteFiles.at(idxProcess);

        // arguments to export files
        QString expoFile = "/data/data/"
                + sqliteFiles.at(idxProcess)
                + "/databases/";
        arguments.clear();
        arguments << "-s" << selectedDevice << "pull"
                  << expoFile
                  << QDir::toNativeSeparators(tmpDir);

        QString cmd4log = command;
        for(int j=0; j<arguments.size(); ++j) {
            cmd4log += ' ';
            cmd4log += arguments.at(j);
        }
        qDebug() << "ExtDevice\t|running:" << cmd4log;
        extDevDlg->setLogTextViewText(cmd4log, Qt::blue);

        // disable closeButton
        extDevDlg->disableCloseButton();

        adbProcess = new QProcess;
        adbProcess->start("adb", arguments);

        connect(adbProcess, SIGNAL(readyReadStandardOutput()),
                this, SLOT(stdoutMsg()));
        connect(adbProcess, SIGNAL(readyReadStandardError()),
                this, SLOT(stderrMsg()));
        connect(adbProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
                this, SLOT(finishedProcess(int,QProcess::ExitStatus)));
    }
}

/**
 * @brief get properties of device
 *
 * @fn ExtDevice::getProperties
 * @param dev
 */
void ExtDevice::getProperties(QString dev)
{
    arguments.clear();
    arguments << "-s" << dev << "shell" << "getprop";

    adbProcess = new QProcess;
    adbProcess->start("adb", arguments);

    connect(adbProcess, SIGNAL(readyReadStandardOutput()),
            this, SLOT(parsePropertiesResult()));
    connect(adbProcess, SIGNAL(readyReadStandardError()),
            this, SLOT(stderrMsg()));
}

/**
 * @brief ExtDevice::getStatus
 * @param dev
 * @return status: at(0)=status, at(1)=rooted, at(2)=id cmd result
 */
QList<QString> ExtDevice::getStatus(QString dev)
{
    QList<QString> status;
    QString idstring;
    QString tmpbuf;

    // is device online/offline
    qDebug() << "ExtDevice\t|getStatus()";
    arguments.clear();
    arguments << "devices";

    adbProcess = new QProcess;

    adbProcess->start("adb", arguments);

    if(!adbProcess->waitForStarted()) {
        qDebug() << "ExtDevice\t|error exec adb command:" << command << arguments.at(0);
        QMessageBox msg(QMessageBox::Warning,
                        tr("Fehler"),
                        tr("adb Befehl konnte nicht ausgeführt werden.\n"
                           "Ist die Android Debug Bridge installiert\n"
                           "und im Systempfad eingetragen?"),
                        QMessageBox::Cancel);
        msg.exec();
        status << "status error";
        return status;
    }
    while(adbProcess->waitForReadyRead()) {
        tmpbuf.append(adbProcess->readAll());
    }
    QList <QString> lines = tmpbuf.split('\n');

    for(int i=1; i<lines.size(); ++i) {     // i=1 to leave out adb header string
        if(lines.at(i).contains(dev)) {
            QString tmp = lines.at(i);
            tmp = tmp.remove(QRegExp(dev));
            status << tmp.simplified();
        }
    }
//    adbProcess->close();

    // is device rooted?
    arguments.clear();
    arguments << "-s" << dev << "shell" << "id";

//    adbProcess = new QProcess;

    adbProcess->start("adb", arguments);

    if(!adbProcess->waitForStarted()) {
        qDebug() << "ExtDevice\t|error exec adb command:" << command << arguments.at(0);
        QMessageBox msg(QMessageBox::Warning,
                        tr("Fehler"),
                        tr("adb Befehl konnte nicht ausgeführt werden.\n"
                           "Ist die Android Debug Bridge installiert\n"
                           "und im Systempfad eingetragen?"),
                        QMessageBox::Cancel);
        msg.exec();
        status << "id error";
        return status;
    }
    while(adbProcess->waitForReadyRead()) {
        idstring.append(adbProcess->readAll());
    }

    if(idstring.contains("uid=0")) {
        deviceRooted = "true";
        status << "true";
        status << idstring;
        qDebug() << "ExtDevice\t|" << arguments;
        qDebug() << "ExtDevice\t|" << idstring;
    }
    else {
        deviceRooted = "false";
        status << "false";
        status << idstring;
        qDebug() << "ExtDevice\t|" << arguments;
        qDebug() << "ExtDevice\t|" << idstring;
    }
    adbProcess->close();

    return status;
}

/**
 * @brief emits expoReady
 *
 * @fn ExtDevice::on_done
 */
void ExtDevice::on_done()
{
    Q_EMIT expoReady(baseDir, selectedDir, selectedDevice);
}


/**
 * @brief get logs of device
 *
 * @fn ExtDevice::on_logRequest
 * @param dev
 */
void ExtDevice::on_logRequest(QString dev)
{
    arguments.clear();
    arguments << "-s" << dev << "shell" << "dmesg";

    adbProcess = new QProcess;
    adbProcess->start("adb", arguments);

    connect(adbProcess, SIGNAL(readyReadStandardOutput()),
            this, SLOT(stdoutMsg()));
    connect(adbProcess, SIGNAL(readyReadStandardError()),
            this, SLOT(stderrMsg()));
}

/**
 * @brief get properties of device
 *
 * @fn ExtDevice::on_propertiesRequest
 * @param dev
 */
void ExtDevice::on_propertiesRequest(QString dev)
{
    arguments.clear();
    arguments << "-s" << dev << "shell" << "getprop";

    adbProcess = new QProcess;
    adbProcess->start("adb", arguments);

    connect(adbProcess, SIGNAL(readyReadStandardOutput()),
            this, SLOT(stdoutMsg()));
    connect(adbProcess, SIGNAL(readyReadStandardError()),
            this, SLOT(stderrMsg()));
}

/**
 * @brief ExtDevice::on_providerRequest
 * @param dev
 */
void ExtDevice::on_providerRequest(QString dev)
{
    qDebug() << "ExtDevice\t| got providerRequest() for:" << dev;

    arguments.clear();
    arguments << "-s" << dev << "shell" << "ls" << "/data/data";

    adbProcess = new QProcess;
    adbProcess->start("adb", arguments);

    connect(adbProcess, SIGNAL(readyReadStandardOutput()),
            this, SLOT(parseProviderResult()));
    connect(adbProcess, SIGNAL(readyReadStandardError()),
            this, SLOT(stderrMsg()));
}

/**
 * @brief ExtDevice::on_providersReady
 * @param providers
 */
void ExtDevice::on_providersReady(QList<QString> providers)
{
    // List of files to export
    sqliteFiles.clear();
    sqliteFiles = providers;

    extDevDlg->setLogTextViewText(tr("Markierte Provider:"), Qt::black);
    Q_FOREACH(QString log, sqliteFiles)
        extDevDlg->setLogTextViewText(log, Qt::black);

    // save providers in ini file
    QList<QVariant> vList;
    for(int i=0; i<sqliteFiles.size(); ++i)
        vList.append(sqliteFiles.at(i));
    QString templatePath = QApplication::applicationDirPath () + "/templates";
    QSettings settings (templatePath + "/PPSettings.ini", QSettings::IniFormat);
    settings.beginGroup("LastProviders");
    settings.setValue("lastProviders", vList);
    settings.endGroup();

    qDebug() << "ExtDevice\t|on_providersReady cought:" << sqliteFiles;
}

/**
 * @brief ExtDevice::on_reloadDevices
 * @note for now this does uid stuff on device dev
 * @param dev
 */
void ExtDevice::on_reloadDevices(QString dev)  //TODO: continue
{
    qDebug() << "ExtDevice\t|in on_reloadDevices. counter =" << counter;
    //QProcess *proc = new QProcess;
    QString output;
    switch(counter) {
    case 0:
    {
        arguments.clear();
        arguments << "-s" << dev << "shell" << "mount";

        QProcess *proc = new QProcess;
        proc->start("adb", arguments);

        if(!proc->waitForStarted()) {
            qDebug() << "ExtDevice\t|error exec adb command:" << command << arguments.at(0);
            return;
        }
        output.append(proc->readAll());

    }
    case 1:
    {
        arguments.clear();
        arguments << "-s" << dev << "shell" << "su -";

        QProcess *proc = new QProcess;
        proc->start("adb", arguments);
        if(!proc->waitForStarted()) {
            qDebug() << "ExtDevice\t|error exec adb command:" << command << arguments.at(0);
            return;
        }
        output.append(proc->readAll());

    }
    case 2:
    {
        arguments.clear();
        arguments << "-s" << dev << "shell" << "id";

        QProcess *proc = new QProcess;
        proc->start("adb", arguments);
        if(!proc->waitForStarted()) {
            qDebug() << "ExtDevice\t|error exec adb command:" << command << arguments.at(0);
            return;
        }
        output.append(proc->readAll());
        counter = 0;
        proc->close();
    }
        ++counter;
        qDebug() << output;
        output.clear();
    }
}

/** @brief parse Device name out of adb devices string
 * @callgraph
 * @callergraph
 *
 * @param QString buf: result of adb devices
 * @returns QList<QString> devices: List of found devices
 */
QList<QString> ExtDevice::parseDevicesResult(QString buf)
{
    QStringList lines;
    QList<QString> devices;
    QString tmp;

//    devices << tr("Gerät auswählen");
    lines = buf.split('\n');

    for(int i=1; i<lines.size(); ++i) {     // i=1 to leave out adb header string
        if(lines.at(i).contains("device")) {
            tmp = lines.at(i);
            tmp = tmp.remove(QRegExp("device"));
            devices << tmp.simplified();
        }
        else if(lines.at(i).contains("offline")) {
            tmp = lines.at(i);
            devices << tmp.simplified();
        }
    }
    return devices;
}

/**
 * @brief get relevant props of device, sets tooltip for device combobox
 *
 * @fn ExtDevice::parsePropertiesResult
 */
void ExtDevice::parsePropertiesResult()
{
    QString tmp;

    QByteArray strdata = adbProcess->readAllStandardOutput();
    QString tmpdata(strdata);
    QList<QString> lines = tmpdata.split('\n');

    for(int i=1; i<lines.size(); ++i) {     // i=1 to leave out adb header string
        if(lines.at(i).contains("ro.product.model")) {
            tmp = lines.at(i);
            tmp = tmp.split(':').at(1);
            deviceModel = tmp.remove('[').remove(']').simplified();
            qDebug() << "ExtDevice\t|Selected Device Model:" << deviceModel;
        }
        else if(lines.at(i).contains("ro.serialno")) {
            tmp = lines.at(i);
            tmp = tmp.split(':').at(1);
            deviceSerialNr = tmp.remove('[').remove(']').simplified();
            qDebug() << "ExtDevice\t|Selected Device SerialNr.:" << deviceSerialNr;
        }
        else if(lines.at(i).contains("ro.product.manufacturer")) {
            tmp = lines.at(i);
            tmp = tmp.split(':').at(1);
            deviceManufacturer = tmp.remove('[').remove(']').simplified();
            qDebug() << "ExtDevice\t|Selected Device Manufactorer:" << deviceManufacturer;
        }
        else if(lines.at(i).contains("ro.build.display.id")) {
            tmp = lines.at(i);
            tmp = tmp.split(':').at(1);
            deviceDisplayId = tmp.remove('[').remove(']').simplified();
            qDebug() << "ExtDevice\t|Selected Device DisplayId:" << deviceDisplayId;
        }
        else if(lines.at(i).contains("ro.build.version.release")) {
            tmp = lines.at(i);
            tmp = tmp.split(':').at(1);
            deviceVersionRelease = tmp.remove('[').remove(']').simplified();
            qDebug() << "ExtDevice\t|Selected Device Version Release:" << deviceVersionRelease;
        }
        else if(lines.at(i).contains("gsm.operator.alpha")) {
            tmp = lines.at(i);
            tmp = tmp.split(':').at(1);
            deviceOperatorAlpha = tmp.remove('[').remove(']').simplified();
            qDebug() << "ExtDevice\t|Selected Device Operator:" << deviceOperatorAlpha;
        }
        else if(lines.at(i).contains("gsm.operator.iso-country")) {
            tmp = lines.at(i);
            tmp = tmp.split(':').at(1);
            deviceIsoCountry = tmp.remove('[').remove(']').simplified();
            qDebug() << "ExtDevice\t|Selected Device Operator Iso-Country:" << deviceIsoCountry;
        }
        else if(lines.at(i).contains("gsm.network.type")) {
            tmp = lines.at(i);
            tmp = tmp.split(':').at(1);
            deviceNetworkType = tmp.remove('[').remove(']').simplified();
            qDebug() << "ExtDevice\t|Selected Device Network Type:" << deviceNetworkType;
        }
        else if(lines.at(i).contains("ro.runtime.firstboot")) {
            tmp = lines.at(i);
            tmp = tmp.split(':').at(1);
            tmp = tmp.remove('[').remove(']').simplified();
            uint timestamp = tmp.toULongLong()/1000;
            QDateTime date = QDateTime::fromTime_t(timestamp);
            deviceFirstboot = date.toString("yyyy-MM-dd, hh:mm UTC");
            qDebug() << "ExtDevice\t|Selected Device Boot timestamp:" << deviceFirstboot;
        }
    }
    QList<QString> stats = getStatus(extDevDlg->getActiveDevice());
    deviceStatus = stats.at(0);
    deviceRooted = stats.at(1);
    deviceUId = stats.at(2);
    QString text =
            tr("Device Model: ") + deviceModel + '\n'
            + tr("Device Manufactorer: ") + deviceManufacturer  + '\n'
            + tr("Device Serialno: ") + deviceSerialNr + '\n'
            + tr("Build Nummer: ") + deviceDisplayId + '\n'
            + tr("Device Version Release: ") + deviceVersionRelease + '\n'
            + tr("Device Last Boot: ") + deviceFirstboot + '\n'
            + tr("Device GSM Operator: ") + deviceOperatorAlpha + " @ " + deviceIsoCountry + '\n'
            + tr("Device Network Type: ") + deviceNetworkType;

    // sets also deviceModelLabel
    extDevDlg->setComboToolTip(deviceStatus,
                               deviceModel,
                               deviceRooted,
                               deviceUId,
                               text);

}

void ExtDevice::parseProviderResult()
{
    qDebug() << "ExtDevice\t|in parseProviderResult()";

    QString tmp;

    QByteArray strdata = adbProcess->readAllStandardOutput();
    QString tmpdata(strdata);
    QList<QString> lines = tmpdata.split('\n');
    lines.removeFirst();

    providerDlg = new ProviderDlg(lines);

    connect(providerDlg, SIGNAL(providersReady(QList<QString>)),
            this, SLOT(on_providersReady(QList<QString>)));

    providerDlg->show();
}

/**
 * @brief emits gotDevice
 *
 * @fn ExtDevice::sendDeviceToMainWindow
 * @param dev
 */
void ExtDevice::sendDeviceToMainWindow(QString dev)
{
    Q_EMIT gotDevice(dev);
}

/**
 * @brief log error to textView
 *
 * @fn ExtDevice::stderrMsg
 */
void ExtDevice::stderrMsg()
{
    QByteArray strdata = adbProcess->readAllStandardError();
    extDevDlg->setLogTextViewText(strdata, Qt::red);
}

/**
 * @brief log message to textView
 *
 * @fn ExtDevice::stdoutMsg
 */
void ExtDevice::stdoutMsg()
{
    QByteArray strdata = adbProcess->readAllStandardOutput();
    extDevDlg->setLogTextViewText(strdata, Qt::gray);
}


